module multiplier(
iClk, // input clock
iReset, // reset signal
iReady, // indicates inputs are ready
oDone, // indicates that the result is ready
iMultiplier, // 8-bit multiplier [7:0]
iMultiplicand, // 8-bit multiplicand [7:0]
oProduct // 16-bit product [15:0]
);
input [7:0] iMultiplier;
input [7:0] iMultiplicand;
input iClk;
input iReset;
input iReady;

output oDone;
output [15:0]oProduct;

wire [15:0] sum1;
wire [15:0] sum2;
wire [15:0] sum3;
wire [15:0] sum4;
wire [15:0] sum5;
wire [15:0] sum6;
wire [15:0] sum7;
wire [15:0] sum8;

wire [15:0] extended; //extended 16-bit digits from multiplicand

assign extended={iMultiplicand[7:0], 8'b0000_0000};

wire [15:0] buffer00;
wire [15:0] buffer01;
wire [15:0] buffer02;
wire [15:0] buffer03;
wire [15:0] buffer04;
wire [15:0] buffer05;
wire [15:0] buffer06;
wire [15:0] buffer07;
wire [15:0] buffer08;
wire [15:0] buffer09;
wire [15:0] buffer10;
wire [15:0] buffer11;
wire [15:0] buffer12;
wire [15:0] buffer13;
wire [15:0] buffer14;
wire [15:0] buffer15;


//determine shifted values//

//determine whether it should be added or not on each bit//
determine d0(extended, iMultiplier[0], sum1);
determine d1(extended, iMultiplier[1], sum2);
determine d2(extended, iMultiplier[2], sum3);
determine d3(extended, iMultiplier[3], sum4);
determine d4(extended, iMultiplier[4], sum5);
determine d5(extended, iMultiplier[5], sum6);
determine d6(extended, iMultiplier[6], sum7);
determine d7(extended, iMultiplier[7], sum8);

//adding when it needed//
assign buffer00=16'b0000_0000_0000_0000;
adder a1(sum1, buffer00, buffer01);
assign buffer02={1'b0, buffer01[15:1]};
adder a2(sum2, buffer02, buffer03);
assign buffer04={1'b0, buffer03[15:1]};
adder a3(sum3, buffer04, buffer05);
assign buffer06={1'b0, buffer05[15:1]};
adder a4(sum4, buffer06, buffer07);
assign buffer08={1'b0, buffer07[15:1]};
adder a5(sum5, buffer08, buffer09);
assign buffer10={1'b0, buffer09[15:1]};
adder a6(sum6, buffer10, buffer11);
assign buffer12={1'b0, buffer11[15:1]};
adder a7(sum7, buffer12, buffer13);
assign buffer14={1'b0, buffer13[15:1]};
adder a8(sum8, buffer14, buffer15, lastcarry);
assign oProduct={lastcarry, buffer15[15:1]};
endmodule

module adder(
input [15:0] a, 
input [15:0] b,
output [15:0] sum,
output lastcarry
);

wire [7:0] c; //carry between bits
wire [23:0] middle;

assign c[0]=0; //assign first carry
assign sum[7:0]=b[7:0];

xor(sum[8],b[8],c[0],a[8]); //determining sum
and(middle[0], a[8], b[8]); 
and(middle[1], a[8], c[0]);
and(middle[2], b[8], c[0]);
or(c[1], middle[0], middle[1], middle[2]);

xor(sum[9],b[9],c[1],a[9]); //determining sum
and(middle[3], a[9], b[9]); 
and(middle[4], a[9], c[1]);
and(middle[5], b[9], c[1]);
or(c[2], middle[3], middle[4], middle[5]);

xor(sum[10],b[10],c[2],a[10]); //determining sum
and(middle[6], a[10], b[10]); 
and(middle[7], a[10], c[2]);
and(middle[8], b[10], c[2]);
or(c[3], middle[6], middle[7], middle[8]);

xor(sum[11],b[11],c[3],a[11]); //determining sum
and(middle[9], a[11], b[11]); 
and(middle[10], a[11], c[3]);
and(middle[11], b[11], c[3]);
or(c[4], middle[9], middle[10], middle[11]);

xor(sum[12],b[12],c[4],a[12]); //determining sum
and(middle[12], a[12], b[12]); 
and(middle[13], a[12], c[4]);
and(middle[14], b[12], c[4]);
or(c[5], middle[12], middle[13], middle[14]);

xor(sum[13],b[13],c[5],a[13]); //determining sum
and(middle[15], a[13], b[13]); 
and(middle[16], a[13], c[5]);
and(middle[17], b[13], c[5]);
or(c[6], middle[15], middle[16], middle[17]);

xor(sum[14],b[14],c[6],a[14]); //determining sum
and(middle[18], a[14], b[14]); 
and(middle[19], a[14], c[6]);
and(middle[20], b[14], c[6]);
or(c[7], middle[18], middle[19], middle[20]);

xor(sum[15],b[15],c[7],a[15]); //determining sum
and(middle[18], a[14], b[14]); 
and(middle[19], a[14], c[6]);
and(middle[20], b[14], c[6]);
or(lastcarry, middle[18], middle[19], middle[20]);


endmodule

module determine(
input [15:0] a,
input d,
output [15:0] b
);

and(b[0], a[0], d);
and(b[1], a[1], d);
and(b[2], a[2], d);
and(b[3], a[3], d);
and(b[4], a[4], d);
and(b[5], a[5], d);
and(b[6], a[6], d);
and(b[7], a[7], d);
and(b[8], a[8], d);
and(b[9], a[9], d);
and(b[10], a[10], d);
and(b[11], a[11], d);
and(b[12], a[12], d);
and(b[13], a[13], d);
and(b[14], a[14], d);
and(b[15], a[15], d);

endmodule

